﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace Tressel_asm
{
    class Instruction
    {
        #region variables
        /*#
        Variable Name: tresselReference
        Module Where Defined: Instruction
        Data Type: TresselIntermediate
        Local or Global: Global
        Purpose: a Global variable been passed throuth class for access of methods and other global varibles
        #*/
        private TresselIntermediate tresselReference;
        /*#
        Variable Name: isSourceGenerated
        Module Where Defined: Instruction
        Data Type: bool
        Local or Global: Global
        Purpose: marks that the instruction came from a sourceLine
        #*/
        private bool isSourceGenerated = true;
        /*#
        Variable Name: hexCode
        Module Where Defined: Instruction
        Data Type: string
        Local or Global: Global
        Purpose: a Global variable storing the hex code for the instruction
        #*/
        private string hexCode = "------";
        /*#
        Variable Name: relocationCode
        Module Where Defined: Instruction
        Data Type: string
        Local or Global: Global
        Purpose: a Global variable storing the relocation code for the instruction
        #*/
        private string relocationCode = "-";
        /*#
        Variable Name: shouldAddInstruction
        Module Where Defined: Instruction
        Data Type: int
        Local or Global: Global
        Purpose: stores whether an instruction should be added to the intermediate collection
        #*/
        private int shouldAddInstruction = 0;
        /*#
        Variable Name: iLabel;
        Module Where Defined: Instruction
        Data Type: Label
        Local or Global: Local
        Purpose: Instance to keep information of label value for the current instruction
        #*/
        private Label iLabel;
        /*#
        Variable Name: iOpcode
        Module Where Defined: Instruction
        Data Type: OpCode
        Local or Global: Local
        Purpose: Instance to keep information of instrcution or directive information for the current instruction
        #*/
        private OpCode iOpcode;
        /*#
        Variable Name: iOperand
        Module Where Defined: Instruction
        Data Type: OpCode
        Local or Global: Local
        Purpose: Instance to keep information of operand value for the current instruction
        #*/
        private Operands iOperands;
        /*#
        Variable Name: iLineCount
        Module Where Defined: Instruction
        Data Type: int
        Local or Global: Local
        Purpose: Instance to keep information of line number for the current instruction
        #*/
        private int iLineCount;
        /*#
        Variable Name: iLocationCount
        Module Where Defined: Instruction
        Data Type: int
        Local or Global: Local
        Purpose: Instance to keep information of LocationCount for the current instruction
        #*/
        private int iLocationCount;
        /*#
        Variable Name: instructionString
        Module Where Defined: Instruction
        Data Type: string
        Local or Global: Local
        Purpose: string of instruction where in format of "label"+"opcode"+"operand"+"comment"
        #*/
        private string instructionString;
        /*#
        Variable Name: hasLiteral
        Module Where Defined: Instruction
        Data Type: bool
        Local or Global: Global
        Purpose:  storing whether or not a literal is in operands
        #*/
        private bool hasLiteral = false;
        /*#
        Variable Name: isValidInstruction
        Module Where Defined: Instruction
        Data Type: bool
        Local or Global: Global
        Purpose:  stores whether or not the instruction is valid
        #*/
        private bool isValidInstruction = true;
        /*#
        Variable Name: DebugRegister
        Module Where Defined: Instruction
        Data Type: string
        Local or Global: Global
        Purpose:  stores whether or not the Debug bit is on
        #*/
        private string debugRegister = "0";
        /*#
        Variable Name: indexRegister
        Module Where Defined: Instruction
        Data Type: string
        Local or Global: Global
        Purpose:  stores whether or not the indexRegister bit is on
        #*/
        private string indexRegister = "0";
        /*#
        Variable Name: baseRegister
        Module Where Defined: Instruction
        Data Type: string
        Local or Global: Global
        Purpose:  stores whether or not the baseRegister bit is on
        #*/
        private string baseRegister = "0";
        /*#
        Variable Name: addressFlags
        Module Where Defined: Instruction
        Data Type: string
        Local or Global: Global
        Purpose:  stores the address flags for the instruction
        #*/
        private string addressFlags;
        /*#
        Variable Name: expectingLDBRADR
        Module Where Defined: ProcessDirectives
        Data Type: bool
        Local or Global: Global
        Purpose:  Used to flag if a USING is found (then LD-BR-ADR is expected).
        #*/
        bool expectingLDBRADR = false;
        #endregion
        /*Procedure Name: ILineCount
        Description: the property making iLineCount publically accessible
        Input Parameters: none
        Output Parameters: returns iLineCount
        Error Conditions Tested:
        Error Messages Generated:
        Original Author: Louis Pan
        Procedure Creation Date: 10/17/2009
        Modification Log:
        Coding Standards Met: SR
        Testing Standards Met: RM
        !*/
        public int ILineCount
        {
            get
            {
                return iLineCount;
            }
            set
            {
                iLineCount = value;
            }
        }
        /*Procedure Name: IsSourceGenerated
        Description: the property making isSourceGenerated publically accessible
        Input Parameters: none
        Output Parameters: returns isSourceGenerated
        Error Conditions Tested:
        Error Messages Generated:
        Original Author: Steve Rudy
        Procedure Creation Date: 11/12/2009
        Modification Log:
        Coding Standards Met: SR
        Testing Standards Met: RM
        !*/
        public bool IsSourceGenerated
        {
            get
            {
                return isSourceGenerated;
            }
        }
        /*
        Procedure Name: IsValidInstruction
        Description: the property making isValidInstruction publically accessible
        Input Parameters: none
        Output Parameters: returns bool
        Error Conditions Tested:
        Error Messages Generated:
        Original Author: Steve Rudy
        Procedure Creation Date: 11/9/2009
        Modification Log:
        Coding Standards Met: SR
        Testing Standards Met: RM
        !*/
        public bool IsValidInstruction
        {
            get
            {
                return isValidInstruction;
            }
            set
            {
                isValidInstruction = value;
            }
        }
        /*Procedure Name: ShouldAddInstruction
        Description: the property making shouldAddInstruction publically accessible
        Input Parameters: none
        Output Parameters: returns shouldAddInstruction
        Error Conditions Tested:
        Error Messages Generated:
        Original Author: Steve Rudy
        Procedure Creation Date: 11/10/2009
        Modification Log:
        Coding Standards Met: SR
        Testing Standards Met: RM
        !*/
        public int ShouldAddInstruction
        {
            get
            {
                return shouldAddInstruction;
            }
            set
            {
                shouldAddInstruction = value;
            }
        }
        /*
        Procedure Name: HexCode
        Description: the property making hexcode publically accessible
        Input Parameters: none
        Output Parameters: returns hexcode
        Error Conditions Tested:
        Error Messages Generated:
        Original Author: Steve Rudy
        Procedure Creation Date: 11/11/2009
        Modification Log:
        Coding Standards Met: SR
        Testing Standards Met: RM
        !*/
        public string HexCode
        {
            get
            {
                return hexCode;
            }
            set
            {
                hexCode = value;
            }
        }
        /*
        Procedure Name: RelocationCode
        Description: the property making relocationCode publically accessible
        Input Parameters: none
        Output Parameters: returns relocationCode
        Error Conditions Tested:
        Error Messages Generated:
        Original Author: Steve Rudy
        Procedure Creation Date: 11/11/2009
        Modification Log:
        Coding Standards Met: SR
        Testing Standards Met: RM
        !*/
        public string RelocationCode
        {
            get
            {
                return relocationCode;
            }
            set
            {
                relocationCode = value;
            }
        }
        /*
        Procedure Name: AddressFlags
        Description: the property making addressFlags publically accessible
        Input Parameters: none
        Output Parameters: returns addressFlags
        Error Conditions Tested:
        Error Messages Generated:
        Original Author: Steve Rudy
        Procedure Creation Date: 10/30/2009
        Modification Log:
        Coding Standards Met: SR
        Testing Standards Met: RM
        !*/
        public string AddressFlags
        {
            get
            {
                return addressFlags;
            }
            set
            {
                addressFlags = value;
            }
        }
        /*
        Procedure Name: ILocationCount
        Description: the property making iLocationCount publically accessible
        Input Parameters: none
        Output Parameters: returns iLocationCount
        Error Conditions Tested:
        Error Messages Generated:
        Original Author: Louis Pan
        Procedure Creation Date: 10/17/2009
        Modification Log:
        Coding Standards Met: SR
        Testing Standards Met: RM
        !*/
        public int ILocationCount
        {
            get
            {
                return iLocationCount;
            }
            set
            {
                iLocationCount = value;
            }
        }
        /*Procedure Name: ILabel
        Description: the property making iLabel publically accessible
        Input Parameters: none
        Output Parameters: returns iLabel
        Error Conditions Tested:
        Error Messages Generated:
        Original Author: Louis Pan
        Procedure Creation Date: 10/17/2009
        Modification Log:
        Coding Standards Met: SR
        Testing Standards Met: RM
        !*/
        public Label ILabel
        {
            get
            {
                return iLabel;
            }
            set
            {
                iLabel = value;
            }
        }
        /*Procedure Name: IOpcode
        Description: the property making iOpcode publically accessible
        Input Parameters: none
        Output Parameters: returns iOpcode
        Error Conditions Tested:
        Error Messages Generated:
        Original Author: Louis Pan
        Procedure Creation Date: 10/17/2009
        Modification Log:
        Coding Standards Met: SR
        Testing Standards Met: RM
        !*/
        public OpCode IOpcode
        {
            get
            {
                return iOpcode;
            }
            set
            {
                iOpcode = value;
            }
        }
        /*Procedure Name: IOperands
        Description: the property making iOperands publically accessible
        Input Parameters: none
        Output Parameters: returns iOperands
        Error Conditions Tested:
        Error Messages Generated:
        Original Author: Louis Pan
        Procedure Creation Date: 10/17/2009
        Modification Log:
        Coding Standards Met:  SR
        Testing Standards Met: RM
        !*/
        public Operands IOperands
        {
            get
            {
                return iOperands;
            }
            set
            {
                iOperands = value;
            }
        }
        public TresselIntermediate TresselReference
        {
            /*!
            Procedure Name: TresselReference
            Description: Used by lesser classes (Label, Opcode, etc.) to gain access to the tables
            stored in the TresselIntermediate class to which this Instruction instance belongs.
            Input Parameters: none
            Output Parameters: TresselIntermediate
            Error Conditions Tested: 
            Error Messages Generated: 
            Original Author: Steve Rudy
            Procedure Creation Date: 10/13/2009
            Modification Log:
            Who: Steve Rudy
            When: 10/27/2009
            Why: this method should become a property
            Coding Standards Met: SR
            Testing Standards Met: RM
            !*/
            get
            {
                return tresselReference;
            }
        }
        public string DebugRegister
        {
            /*!
            Procedure Name: DebugRegister
            Description: Used by objectfile classes to gain access to the debug register
            Input Parameters: none
            Output Parameters: string
            Error Conditions Tested: 
            Error Messages Generated: 
            Original Author: Louis Pan
            Procedure Creation Date: 10/28/2009
            Modification Log:
            Who: Steve Rudy
            When: 11/2/2009
            Why: i was returning the property itself, which created an infinite loop.
            Coding Standards Met: SR
            Testing Standards Met: RM
            !*/
            get
            {
                return debugRegister;
            }
        }
        public string IndexRegister
        {
            /*!
            Procedure Name: IndexRegister
            Description: Used by objectfile classes to gain access to the index register
            Input Parameters: none
            Output Parameters: string
            Error Conditions Tested: 
            Error Messages Generated: 
            Original Author: Steve Rudy
            Procedure Creation Date: 10/30/2009
            Modification Log:
            Coding Standards Met: SR
            Testing Standards Met: RM
            !*/
            get
            {
                return indexRegister;
            }
        }
        public string BaseRegister
        {
            /*!
            Procedure Name: BaseRegister
            Description: Used by objectfile classes to gain access to the base register
            Input Parameters: none
            Output Parameters: string
            Error Conditions Tested: 
            Error Messages Generated: 
            Original Author: Steve Rudy
            Procedure Creation Date: 10/30/2009
            Modification Log:
            Coding Standards Met: SR
            Testing Standards Met: RM
            !*/
            get
            {
                return baseRegister;
            }
        }
        public void AddError(int errorNumber)
        {
            /*!
            Procedure Name: AddError
            Description: Created for lesser classes to report errors by adding them to the generated
            error table
            Input Parameters: int errorNumber (the index of the error)
            Output Parameters: none
            Error Conditions Tested: 
            Error Messages Generated: 
            Original Author: Steve Rudy
            Procedure Creation Date: 10/14/2009
            Modification Log:
            Coding Standards Met: SR
            Testing Standards Met: RM 
            !*/
            this.tresselReference.InsertIntoErrorTable(tresselReference.LineCounter, errorNumber);
        }
        public Instruction(string label, string opcode, string operands, TresselIntermediate tresselReferenceParam)
        {
            /*!
            Procedure Name: Instruction (2nd version)
            Description: second constructor for adding literals to end of program
            Input Parameters: string label, string opcode, string operands, TresselIntermediate tresselReferenceParam
            Output Parameters: none
            Error Conditions Tested: 
            Error Messages Generated: 
            Original Author: Steve Rudy
            Procedure Creation Date: 10/21/2009
            Modification Log:
            Who: Steve Rudy
            When: 11/12/2009
            Why: set the isSourceGenerated member boolean to false
            Coding Standards Met: SR
            Testing Standards Met: RM 
            !*/
            isSourceGenerated = false;
            this.iLabel = new Label();
            this.iOpcode = new OpCode();
            this.iOperands = new Operands();
            tresselReferenceParam.LocationCounter++;
            this.iLocationCount = tresselReferenceParam.LocationCounter;
            this.iLineCount = tresselReferenceParam.LineCounter;
            iLabel.Text  = label;
            iOpcode.Text = opcode;
            iOperands.Text = operands;
            debugRegister = tresselReferenceParam.DebugRegisterState;
            baseRegister = tresselReferenceParam.BaseRegisterState;
            shouldAddInstruction = 2;
            this.IOpcode.TakesUpMemory = "YES";
            this.IOpcode.LabelReq = "OL";
        }

        public Instruction(string nextLine, TresselIntermediate tresselReferenceParam,bool isSourceGeneratedParam)
        {
            /*!
            Procedure Name: Instruction
            Description: Constructor for type Instruction
            Input Parameters: string nextLine , TresselIntermediate tresselReferenceParam
            Output Parameters: none
            Error Conditions Tested: 
            Error Messages Generated: 
            Original Author: Steve Rudy
            Procedure Creation Date: 10/10/2009
            Modification Log:
            Who: Steve Rudy
            When: 11/12/2009
            Why: added setting the isSourceGenerated member to the newly added isSourceGeneratedParam
            Coding Standards Met: SR
            Testing Standards Met: RM
            !*/
            tresselReference = tresselReferenceParam;
            isSourceGenerated = isSourceGeneratedParam;
            this.debugRegister = tresselReference.DebugRegisterState;
            this.baseRegister = tresselReference.BaseRegisterState;
            this.instructionString = nextLine;
        }
        public void Parse()
        {
            /*!
            Procedure Name: Parse
            Description: The main method of the Instruction class, it breaks down the instruction to its
            separate components and generates an Instruction object.
            Input Parameters: none
            Output Parameters: none
            Error Conditions Tested: General Instrution Operand opcode label syntax checked 
            Error Messages Generated:
                (See Error message table for descriptive messages)
                [5,18,56,47,54,1,20,17,15,25]  
            Original Author: Steve Rudy
            Procedure Creation Date: 10/9/2009
            Modification Log:
            Who: Steve Rudy
            When: 10/14/2009
            Why: We can't check the label, opcode, operands, then comment.  We must first go to the
            opcode, which provides information on the format of the operands and the necessity of a
            label.
            Who: Louis Pan/Ryan Mcdaniel
            When: 10/17/2009
            Why: Design an exception list for normal parsing.  When specific mneumonics are read in they are handled differently.
            Who: Louis Pan/Ryan Mcdaniel
            When: 10/18/2009
            Why: Create the code for all individually handled opcode instructions. 
            Who: Steve Rudy
            When: 10/21/2009
            Why: Label-error reporting needs to be improved
            Who: Louis Pan
            When: 10/27/2009
            Why: extra processing directives need to be done in a separate method
            Who: Louis Pan
            When: 10/28/2009
            Why  skipmem modified so it won't increment locationcounter when out of bound.
            Who: Steve Rudy
            When: 10/30/2009
            Why: changing literal values to use '' when they go into the symbol table
            Who: Steve Rudy
            When: 11/6/2009
            Why: Parse did not account for characters in literals or word-chrs that appear after the ending single quote
            Who: Steve Rudy
            When: 11/6/2009
            Why: we needed to convert the NOP instructions to shift-rotate-left 0
            Who: Steve Rudy
            When: 11/15/2009
            Why: needed to account for clearing duplicate START lines
            Coding Standards Met: SR
            Testing Standards Met: RM
            !*/

            /*#
            Variable Name: whitespace
            Module Where Defined: Parse
            Data Type: char[]
            Local or Global: Local
            Purpose:  set of space and tab that help parse a string line
            #*/
            char[] whitespace = { ' ', '\t' };
            /*#
            Variable Name: potentialLabel
            Module Where Defined: Parse
            Data Type: string
            Local or Global: Local
            Purpose:  string value of possible Label for iLabel
            #*/
            string potentialLabel = "";
            /*#
            Variable Name: potentialOpcode
            Module Where Defined: Parse
            Data Type: string
            Local or Global: Local
            Purpose:  string value of possible Opcode for iOpcode
            #*/
            string potentialOpcode = "";
            /*#
            Variable Name: potentialOperands
            Module Where Defined: Parse
            Data Type: string
            Local or Global: Local
            Purpose:  string value of possible operands for iOperands
            #*/
            string potentialOperands = "";
            /*#
            Variable Name: potentialcomment
            Module Where Defined: Parse
            Data Type: string
            Local or Global: Local
            Purpose:  string value of possible comment for error checking
            #*/
            string potentialComment = "";
            /*#
            Variable Name: shouldAddLabel
            Module Where Defined: Parse
            Data Type: bool
            Local or Global: Local
            Purpose:  storing whether or not a label should be added
            #*/
            bool shouldAddLabel = true;
            


            if (instructionString.Length > 0)
            {
                this.iLabel = new Label();
                this.iOpcode = new OpCode();
                this.iOperands = new Operands();
                this.iLocationCount = tresselReference.LocationCounter;
                this.iLineCount = tresselReference.LineCounter;

                if (instructionString.TrimStart(whitespace).Equals(instructionString))
                {
                    iLabel = new Label(TrimNextWord(), this);
                    iLabel.IsGenerated = true;
                }
                if (instructionString.Trim().StartsWith(":"))
                {
                    AddError(5);
                    iOpcode.ErrorFlag = true;
                }
                else
                {
                    this.iOpcode = new OpCode(TrimNextWord(), this);
                    if (this.iLineCount != 0 && !tresselReference.StartsBeenFound)
                    {
                        AddError(18);
                        tresselReference.FatalErrors = true;
                        return;
                    }
                    if (tresselReference.BaseRegisterState.Equals("1") && iLineCount == 2 && !iOpcode.Text.Equals("LD-BR-ADR"))
                    {
                        AddError(56);
                        tresselReference.FatalErrors = true;
                        return;
                    }
                    
                    
                    if (iOpcode.Text.Equals("START"))
                    {
                        if (this.iLineCount != 0 && !tresselReference.StartsBeenFound)
                        {
                            AddError(18);
                            tresselReference.FatalErrors = true;
                            return;
                        }
                        tresselReference.StartsBeenFound = true;
                    }

                    if (expectingLDBRADR && !iOpcode.Text.Equals("LD-BR-ADR"))
                    {
                        AddError(56);
                        tresselReference.FatalErrors = true;
                        return;
                    }
                    else
                    {
                        expectingLDBRADR = false;
                    }
                }
                if (!iOpcode.ErrorFlag)
                {
                    if (!iOpcode.OperandReq.Equals("@NONE") && !instructionString.Trim().StartsWith(":"))
                    {
                        if (instructionString.Trim().StartsWith("="))
                        {
                            instructionString = instructionString.Trim().Remove(0, 1);
                            hasLiteral = true;
                        }
                        if (instructionString.Trim().StartsWith("'"))
                        {
                            /*#
                            Variable Name: endIndex
                            Module Where Defined: Parse
                            Data Type: int
                            Local or Global: Local
                            Purpose:  stores the location of the final single quote in the operand
                            #*/
                            int endIndex = -1;
                            instructionString = instructionString.TrimStart(whitespace);
                            for (int i = 1; i < instructionString.Length && i < 5; i++)
                            {
                                /*#
                                Variable Name: tempInt
                                Module Where Defined: Parse
                                Data Type: int
                                Local or Global: Local
                                Purpose:  stores the location of the single quote in the operand after index i
                                #*/
                                int tempInt = instructionString.IndexOf("'", i);
                                if (tempInt > endIndex)
                                {
                                    endIndex = tempInt;
                                }
                            }
                            endIndex = endIndex + 1;
                            potentialOperands = instructionString.Substring(0, endIndex);
                            instructionString = instructionString.Substring(endIndex, instructionString.Length - endIndex);
                            if (instructionString.TrimStart(whitespace).Equals(instructionString))
                            {
                                potentialOperands = potentialOperands + TrimNextWord();
                            }
                            if (potentialOperands.Length <= 2)
                            {
                                AddError(47);
                                hasLiteral = false;
                                isValidInstruction = false;
                                potentialOperands = "";
                            }
                        }
                        else
                        {
                            potentialOperands = TrimNextWord();
                            if (potentialOperands.ToUpper().EndsWith(",IR"))
                            {
                                indexRegister = "1";
                                potentialOperands = potentialOperands.Remove(potentialOperands.Length - 3);
                            }
                            if (potentialOperands.StartsWith("*") && !(iOpcode.Text.Equals("LD-BR-ADR")) && !(iOpcode.Text.Equals("EQU")) &&!(iOpcode.Text.Equals("ADR-COMP")))
                            
                            {
                                potentialOperands = potentialOperands.Remove(0, 1);
                                potentialOperands = tresselReference.LocationCounter.ToString() + potentialOperands;
                                /*#
                                Variable Name: tempOperator
                                Module Where Defined: Parse
                                Data Type: int
                                Local or Global: Local
                                Purpose:  stores the location of + and -
                                #*/
                                int[] tempOperator = new int[2];
                                tempOperator[0] = potentialOperands.IndexOf('+');
                                tempOperator[1] = potentialOperands.IndexOf('-');
                               
                                if (tempOperator[1] < tempOperator[0] )
                                {
                                    if (tempOperator[1] > 0)
                                    {
                                        tempOperator[0] = tempOperator[1];
                                    }
                                }
                                else if (tempOperator[0] < 0)
                                {
                                    tempOperator[0] = tempOperator[1];
                                }

                                if (tempOperator[0] > 0)
                                {
                                    /*#
                                   Variable Name: temp1
                                   Module Where Defined: Parse
                                   Data Type: string
                                   Local or Global: Local
                                   Purpose:  stores first part of operands.
                                   #*/
                                    string temp1 = potentialOperands.Substring(0, tempOperator[0]);
                                    /*#
                                      Variable Name: temp2
                                      Module Where Defined: Parse
                                      Data Type: string
                                      Local or Global: Local
                                      Purpose:  stores second part of operands.
                                      #*/
                                    string temp2 = potentialOperands.Substring(tempOperator[0]);
                                    /*#
                                      Variable Name: sum
                                      Module Where Defined: Parse
                                      Data Type: string
                                      Local or Global: Local
                                      Purpose:  store the result from current location and first operantion
                                      #*/
                                    int sum = 0;

                                    bool ErrorFlag = false;
                                    try
                                    {
                                        sum = System.Convert.ToInt32(temp2);
                                        
                                        sum = int.Parse(temp1) + sum;
                                    }
                                    catch
                                    {
                                        ErrorFlag = true;
                                        
                                    }
                                    if (!ErrorFlag)
                                    {
                                        potentialOperands = sum.ToString();
                                    }
                                }
                            }
                            else if ((iOpcode.Text.Equals("EQU") && potentialOperands.StartsWith("*")) || (iOpcode.Text.Equals("ADR-COMP") && potentialOperands.StartsWith("*")))
                            {
                                potentialOperands = potentialOperands.Remove(0, 1);
                                potentialOperands = tresselReference.LocationCounter.ToString() + potentialOperands;
                            }
                        }
                        if (this.hasDoubleOperator(potentialOperands))
                        {
                            this.AddError(54);
                            if (!iOpcode.Text.Equals("EQU-EXP"))
                            {
                                SetToNop();
                            }
                            else
                            {
                                return;
                            }
                        }

                        if (hasLiteral)
                        {
                            potentialOperands = "=" + potentialOperands;
                        }
                        this.iOperands = new Operands(potentialOperands, this, iOpcode.OperandReq);

                        
                    }
                    potentialComment = instructionString;
                    ProcessDirectives();
                    if (shouldAddInstruction == 0)
                    {
                        shouldAddInstruction = 2;
                    }
                    potentialComment = potentialComment.TrimStart(whitespace);
                    if (!potentialComment.StartsWith(":") && potentialComment.Length > 0)
                    {
                        this.AddError(1);
                    }
                }
                else
                {
                    isValidInstruction = false;
                    if (iLineCount == 0)
                    {
                        AddError(18);
                        tresselReference.FatalErrors = true;
                        return;
                    }
                }
                if (!isValidInstruction)
                {
                    this.SetToNop();
                }
                if ((shouldAddInstruction == 2 || iOpcode.Text.Equals("SKIP-MEM")) && (!iOpcode.Text.Equals("EQU")))
                {
                    if (iLabel.IsGenerated)
                    {
                        if (!iLabel.ErrorFlag)
                        {
                            /*#
                            Variable Name: isDuplicate
                            Module Where Defined: Parse
                            Data Type: int
                            Local or Global: Local
                            Purpose:  keeps track of whether or not the label is a duplicate
                            #*/
                            bool isDuplicate = false;
                            /*#
                            Variable Name: numOfRows
                            Module Where Defined: Parse
                            Data Type: int
                            Local or Global: Local
                            Purpose:  holds the number of returned rows, answering whether or not the label in question is a duplicate
                            #*/
                            int numOfRows = (tresselReference.SymbolTable.Select("[Label Name]='" + iLabel.Text + "'")).Count();
                            if (!(numOfRows == 0))
                            {
                                isDuplicate = true;
                                AddError(20);
                            }
                            if (iOpcode.LabelReq.Equals("RL"))
                            {
                                if (iOperands.Text.Equals("START") && iLabel.ErrorFlag)
                                {
                                    AddError(17);
                                    tresselReference.FatalErrors = true;
                                    return;
                                }

                                if (isDuplicate)
                                {
                                    AddError(20);
                                    return;
                                }
                                else if (iLabel.ErrorFlag)
                                {
                                    return;
                                }
                                else
                                {
                                    string usage = "";
                                    if (iOpcode.Text.Equals("START"))
                                    {
                                        usage = "Pgm Name";
                                    }
                                    tresselReference.InsertSymbol(iLabel.Text, tresselReference.LocationCounter.ToString(), usage, "", "");
                                }
                            }
                            else if (iOpcode.LabelReq.Equals("OL"))
                            {
                                if (isDuplicate)
                                {
                                    iLabel.Text = "";
                                }
                                else
                                {
                                    tresselReference.InsertSymbol(iLabel.Text, tresselReference.LocationCounter.ToString(), "Label", "", "");
                                }
                            }
                            else
                            {
                                AddError(1);
                                this.iLabel.Text = "";
                            }
                        }
                        else
                        {
                            if (iOpcode.LabelReq.Equals("RL"))
                            {
                                if (iOpcode.Text.Equals("START"))
                                {
                                    AddError(17);
                                    tresselReference.FatalErrors = true;
                                    return;
                                }
                                AddError(15);
                                SetToNop();
                            }
                            if (iOpcode.LabelReq.Equals("OL"))
                            {
                                iLabel.Text = "";
                            }
                            else
                            {
                                iLabel.Text = "";
                            }
                        }
                    }
                    else
                    {
                        if (iOpcode.LabelReq.Equals("RL"))
                        {
                            if (iOpcode.Text.Equals("START"))
                            {
                                AddError(25);
                                tresselReference.FatalErrors = true;
                                return;
                            }
                            AddError(15);
                            SetToNop();
                        }
                    }
                }
                if (hasLiteral && iOperands.Text.StartsWith("=") && !iOperands.ErrorFlag)
                {
                    string literalValue = iOperands.Text;
                    int index = iOperands.Text.IndexOf(",");
                    if (index != -1)
                    {
                        literalValue = literalValue.Substring(0, index);
                    }
                    if (tresselReference.SymbolTable.Select("[Label Name]='" + literalValue.Replace("'","''") + "'").Length == 0)
                    {
                        tresselReference.InsertSymbol(literalValue, "", "Literal", literalValue.Remove(0, 1), "");
                    }
                }
                this.iLineCount = tresselReference.LineCounter;
                if (iOpcode.TakesUpMemory.Equals("YES") || !isValidInstruction)
                {
                    this.iLocationCount = tresselReference.LocationCounter;
                    tresselReference.LocationCounter++;
                }
                if (shouldAddInstruction == 2)
                {
                    if (iOperands.Text.StartsWith("%"))
                    {
                        if (baseRegister.Equals("1"))
                        {
                            addressFlags = "011";
                        }
                        else
                        {
                            addressFlags = "010";
                        }
                    }
                    else if (iOperands.Text.StartsWith("#"))
                    {
                        addressFlags = "100";
                    }
                    else
                    {
                        if (baseRegister.Equals("1"))
                        {
                            addressFlags = "001";
                        }
                        else
                        {
                            addressFlags = "000";
                        }
                    }

                    //need to add stuff to handle effective address
                    if (iOpcode.Text.Equals("NOP"))
                    {
                        iOpcode.BinaryCode = "011110";
                        iOperands.Text = "";
                    }
                    tresselReference.InsertInstruction(this);
                }
            }
        }
        private void ProcessDirectives()
        {
            /*!
            Procedure Name: Processdirectives
            Description: Sub-method for parse() to process all the special case of Directives.
            Input Parameters: none
            Output Parameters: none
            Error Conditions Tested: All of the special Directive cases syntax check such as using, equ etc.
            Error Messages Generated:
                (See Error message table for descriptive messages)
                [21,58,23,60,11,19,24,31,15,16,7,28,35,46,16,30
            Original Author: Steve Rudy
            Procedure Creation Date: 10/25/2009
            Modification Log:
            Who: Louis Pan
            When: 10/28/2009
            Why  skipmem modified so it won't increment locationcounter when out of bound.
            Who: Steve Rudy
            When: 10/30/2009
            Why: debug is now a string, and needs to be treated as such
            Who: Louis Pan
            When: 11/1/2009
            Why: external operands add to symbol table
            Who: Steve Rudy
            When: 11/7/2009
            Why: the operands text, when searched within a table, needs each single quote to e replaced with two single quotes
            Who: Steve Rudy
            When: 11/11/2009
            Why: RESET-LC should not be added to the intermediate file
            Who: Steve Rudy
            When: 11/14/2009
            Why: LD-BR-ADR * will replace * with the location counter
            Who: Ryan McDaniel
            When: 11/14/2009
            Why: Removed a check on entry.
            Coding Standards Met: SR
            Testing Standards Met: RM
            !*/



            if (iOpcode.Text.Equals("COMP"))
            {
                ParseComp(iOperands.Text, iLabel.Text);
                if (!iOpcode.Text.Equals("NOP"))
                {
                    shouldAddInstruction = 1;
                }
                else
                {
                    shouldAddInstruction = 2;
                }

            }
            else if (iOpcode.Text.Equals("START"))
            {
                shouldAddInstruction = 2;
                if (tresselReference.LineCounter != 0)
                {
                    this.AddError(21);
                    //isValidInstruction = false;
                    shouldAddInstruction = 1;
                }
                else if (tresselReference.LocationCounter != 0)
                {
                    this.AddError(21);
                    shouldAddInstruction = 1;
                    //isValidInstruction = false;
                }
                else if (!IOperands.ErrorFlag)
                {
                    tresselReference.LocationCounter = int.Parse(IOperands.Text);
                    this.iLocationCount = int.Parse(IOperands.Text);
                    tresselReference.StartingLocationCounter = iLocationCount;
                }
            }

            else if (iOpcode.Text.Equals("END"))
            {
                shouldAddInstruction = 2;
                tresselReference.ProgramEnds = true;


            }
            else if (iOpcode.Text.Equals("USING"))
            {
                if (tresselReference.BaseRegisterState.Equals("1"))
                {
                    AddError(58);
                    tresselReference.FatalErrors = true;
                    return;
                }
                if (tresselReference.LocationCounter != tresselReference.StartingLocationCounter)
                {
                    AddError(23);
                    tresselReference.FatalErrors = true;
                    tresselReference.BaseRegisterState = "0";
                    return;
                }
                tresselReference.BaseRegisterState = "1";
                expectingLDBRADR = true;
            }
            else if (iOpcode.Text.Equals("LD-BR-ADR"))
            {           
                if (tresselReference.LocationCounter != tresselReference.StartingLocationCounter)
                {
                    this.AddError(23);
                    tresselReference.FatalErrors = true;
                    return;
                }
                else
                {
                    iOperands.Text = tresselReference.LocationCounter.ToString();
                    shouldAddInstruction = 2;
                }
            }
            else if (iOpcode.Text.Equals("ADR-COMP"))
            {
                if (iOperands.Text.Contains("*") || iOperands.Text.Contains("/"))
                {
                    AddError(60);
                    SetToNop();
                }
                if (GetTotalOperators(iOperands.Text) > 5)
                {
                    AddError(11);
                    SetToNop();
                }
                if (iOperands.Text.StartsWith("-") || iOperands.Text.StartsWith("+") || iOperands.Text.EndsWith("+") || iOperands.Text.EndsWith("-"))
                {
                    AddError(11);
                    SetToNop();
                }
            }
            
            else if (iOpcode.Text.Equals("RESET-LC"))
            {
                /*#
                Variable Name: lcValue
                Module Where Defined: Parse
                Data Type: int
                Local or Global: Local
                Purpose:  value for possible location count
                #*/
                int lcValue = 0;
                /*#
                Variable Name: rowNum1
                Module Where Defined: Parse
                Data Type: int
                Local or Global: Local
                Purpose:  keep track of number of rows get returned from symbol table, should only be 1 or 0;
                #*/
                int rowNum = (tresselReference.SymbolTable.Select("[Label Name]='" + iOperands.Text + "'")).Count();
                shouldAddInstruction = 1;
                if (rowNum > 0)
                {
                    lcValue = int.Parse(((System.Data.DataRow)(tresselReference.SymbolTable.Select("[Label Name]='" + iOperands.Text + "'").GetValue(0)))["Substitution String"].ToString());
                }
                else
                {
                    int tempIndex = 0;

                    while (tempIndex < iOperands.Text.Length)
                    {
                        if (!char.IsDigit(iOperands.Text[tempIndex]))
                        {
                            this.AddError(19);
                            return;
                        }

                        tempIndex++;
                    }
                    lcValue = int.Parse(iOperands.Text);
                }
                if (lcValue <= tresselReference.LocationCounter)
                {
                    this.AddError(24);
                }
                else if (lcValue > 2047)
                {
                    AddError(31);
                }
                else
                {
                    tresselReference.LocationCounter = lcValue;
                    //tresselReference.InsertInstruction(this);
                    if (iLabel.Text != "")
                    {
                        //asdf
                        rowNum = (tresselReference.SymbolTable.Select("[Label Name]='" + iLabel.Text + "'")).Count();
                        if (rowNum > 0)
                        {
                            AddError(20);
                        }
                        else
                        {
                            if (iLabel.Text.Trim().Length > 0)
                            {
                                tresselReference.InsertSymbol(iLabel.Text, tresselReference.LocationCounter.ToString(), "Label", "", "");
                            }
                        }
                    }
                }
            }

            else if (iOpcode.Text.Equals("ENTRY"))
            {
                if (iOperands.Text.Length == 0)
                {
                    shouldAddInstruction = 1;
                }
            }
            else if (iOpcode.Text.Equals("EQU"))
            {
                shouldAddInstruction = 2;
                if (iLabel.Text.Equals(""))
                {
                    AddError(15);
                    shouldAddInstruction = 1;
                }
                else if (iOperands.Text.Equals(""))
                {
                    AddError(16);
                    shouldAddInstruction = 1;
                }
                else if (iLabel.ErrorFlag || iOperands.ErrorFlag)
                {
                    shouldAddInstruction = 1;
                    return;
                }
                else
                {
                    /*#
                    Variable Name: rowNum2
                    Module Where Defined: Parse
                    Data Type: int
                    Local or Global: Local
                    Purpose:  keep track of number of rows get returned from symbol table, should only be 1 or 0;
                    #*/
                    int rowNum = (tresselReference.SymbolTable.Select("[Label Name]='" + iLabel.Text + "'")).Count();
                    if (rowNum > 0)
                    {
                        AddError(7);
                        shouldAddInstruction = 1;
                        return;
                    }
                    else
                    {

                        if (iLabel.Text.Trim().Length > 0)
                        {
                            System.Data.DataRow[] myRow = tresselReference.SymbolTable.Select("[Label Name]='" + iOperands.Text.Replace("'", "''") + "'");
                            if (myRow.Length == 0)
                            {
                                for (int i = 0; i < iOperands.Text.Length; i++)
                                {
                                    if (!char.IsDigit(iOperands.Text[i]))
                                    {
                                        AddError(11);
                                        iOperands.ErrorFlag = true;
                                        shouldAddInstruction = 1;
                                        break;
                                    }
                                }
                                if (!iOperands.ErrorFlag)
                                {
                                    tresselReference.InsertSymbol(iLabel.Text, "", "EQU", iOperands.Text, "");
                                }

                            }
                            else
                            {
                                if (((System.Data.DataRow)(myRow[0]))["Usage"].ToString().Equals("EQU"))
                                {

                                    iOperands.Text = myRow[0]["Substitution String"].ToString();
                                    tresselReference.InsertSymbol(iLabel.Text, "", "EQU", iOperands.Text, "");

                                }
                                else
                                {

                                    this.AddError(28);
                                    iOperands.Text = "0";
                                    shouldAddInstruction = 1;
                                    return;
                                }
                            }
                        }
                    }
                }
            }

            else if (iOpcode.Text.Equals("EQU-EXP"))
            {
                if (iLabel.Text.Length > 0)
                {
                    if (iOperands.Text.Length > 0)
                    {
                        ParseEquExp(iOperands.Text, iLabel.Text);
                    }
                    else
                    {
                        AddError(11);
                        shouldAddInstruction = 1;
                    }
                }
                else
                {
                    AddError(15);
                    shouldAddInstruction = 1;
                }

            }
            else if (iOpcode.Text.Equals("EXTERNAL"))
            {
                if (iOperands.Text.Length > 0)
                {
                    char comma = ',';
                    char[] commaArray = new char[1];
                    commaArray[0] = comma;

                    /*#
                   Variable Name: splitByComma
                   Module Where Defined: Operands
                   Data Type: String Array
                   Local or Global: Local
                   Purpose: Contains the portions of the string that was split. This holds potential labels.
                   #*/
                    string[] splitByCommas = iOperands.Text.Split(commaArray);

                    for (int i = 0; i < splitByCommas.Length; i++)
                    {
                        if ((tresselReference.SymbolTable.Select("[Label Name]='" + splitByCommas[i].ToString() + "'")).Count() > 0)
                        {

                            AddError(35);
                            splitByCommas[i] = "";
                        }
                        else if ((tresselReference.SymbolTable.Select("[Label Name]='" + splitByCommas[i].ToString() + "'")).Count() == 0 && (splitByCommas[i].ToString().Length >= 2))
                        {
                            tresselReference.InsertSymbol(splitByCommas[i].ToString(), "", "External", "", "C");
                        }
                    }
                    iOperands.Text = "";
                    for (int i = 0; i < splitByCommas.Length; i++)
                    {
                        if (splitByCommas[i].Length > 0)
                        {
                            iOperands.Text += splitByCommas[i].ToString() + ",";
                        }

                    }
                    iOperands.Text = iOperands.Text.TrimEnd(commaArray);
                    if (iOperands.Text.Length == 0)
                    {
                        shouldAddInstruction = 1;
                    }
                }
                else
                {
                    shouldAddInstruction = 1;
                }

            }

            else if (iOpcode.Text.Equals("DEBUG"))
            {
                if (iOperands.Text.ToUpper().Equals("ON"))
                {
                    tresselReference.DebugRegisterState = "1";
                    this.debugRegister = "1";
                }
                else
                {
                    tresselReference.DebugRegisterState = "0";
                    this.debugRegister = "0";

                }
            }
            else if (iOpcode.Text.Equals("HALT"))
            {
                tresselReference.DebugRegisterState = "0";
                if (iOperands.ErrorFlag)
                {
                    iOperands.Text = "0";
                }
            }
            else if (iOpcode.Text.Equals("ALT-START"))
            {
                //tresselReference.InsertInstruction(this);

                if (!tresselReference.AltStartExist)
                {
                    if (Char.IsDigit(iOperands.Text[0]))
                    {
                        if (int.Parse(iOperands.Text) < tresselReference.LocationCounter || int.Parse(iOperands.Text) < tresselReference.StartingLocationCounter)
                        {
                            AddError(46);
                            shouldAddInstruction = 1;
                        }
                        else
                        {
                            tresselReference.AltStartExist = true;
                        }
                    }
                    else
                    {
                        DataRow[] selectedLabels = tresselReference.SymbolTable.Select("[Label Name]=" + "'" + iOperands.Text.Replace("'", "''") + "'");
                        if (selectedLabels.Length == 1 && selectedLabels[0]["Usage"].ToString().Equals("EQU"))
                        {
                            if (int.Parse(selectedLabels[0]["Substitution String"].ToString()) < tresselReference.LocationCounter || int.Parse(selectedLabels[0]["Substitution String"].ToString()) < tresselReference.StartingLocationCounter)
                            {
                                AddError(46);
                                shouldAddInstruction = 1;
                            }
                            else
                            {
                                tresselReference.AltStartExist = true;
                            }
                        }
                        else
                        {
                            AddError(11);
                            shouldAddInstruction = 1;
                        }
                    }
                }
            }
            else if (iOpcode.Text.Equals("SKIP-MEM"))
            {
                shouldAddInstruction = 1;

                if ((tresselReference.SymbolTable.Select("[Label Name]='" + iOperands.Text + "'")).Count() > 0)
                {
                    if (!(((System.Data.DataRow)(tresselReference.SymbolTable.Select("[Label Name]='" + iOperands.Text + "'").GetValue(0)))["Usage"].ToString().Equals("EQU")))//to check error that the label is a equ
                    {
                        this.AddError(16);
                        iOperands.Text = "0";

                    }
                    else
                    {
                        iOperands.Text = (((System.Data.DataRow)(tresselReference.SymbolTable.Select("[Label Name]='" + iOperands.Text + "'").GetValue(0)))["Substitution String"]).ToString();
                    }
                    if ((tresselReference.LocationCounter + int.Parse(iOperands.Text)) > 2047)
                    {
                        this.AddError(31);
                        iOperands.Text = "0";
                    }
                    tresselReference.LocationCounter += int.Parse(iOperands.Text);
                }
                else
                {

                    int tempIndex = 0;

                    while (tempIndex < iOperands.Text.Length)
                    {
                        if (!char.IsDigit(iOperands.Text[tempIndex]))
                        {
                            this.AddError(30);
                            iOperands.Text = "0";
                            shouldAddInstruction = 1;
                            return;
                        }

                        tempIndex++;
                    }
                    if ((tresselReference.LocationCounter + int.Parse(iOperands.Text)) > 4095)
                    {
                        this.AddError(31);
                        iOperands.Text = "0";
                    }
                    tresselReference.LocationCounter += int.Parse(iOperands.Text);
                }
                shouldAddInstruction = 1;

            }
        }
        public void SetToNop()
        {
            /*!
            Procedure Name: SetToNop
            Description: This causes all components of an instruction to be cleared and the opcode set
            to nop.  This is called for intermediate errors.
            Input Parameters: none
            Output Parameters: none
            Error Conditions Tested: 
            Error Messages Generated: 
            Original Author: Steve Rudy
            Procedure Creation Date: 10/15/2009
            Modification Log:
            Who: Louis
            When: 10/17/2009
            Why: the Label should not be cleared, only the other properties
            Coding Standards Met: SR
            Testing Standards Met: RM
            !*/
            this.iOpcode.Text = "NOP";
            this.iOpcode.LabelReq = "OL";
            this.iOpcode.TakesUpMemory = "YES";
            this.iOperands.Text = "";
            hasLiteral = false;
            this.shouldAddInstruction = 2;
        }
        #region Parsing Expressions
        private void ParseEquExp(string equExpOperands, string equLabel)
        {
            /*!
            Procedure Name: ParseEquExp
            Description: The method to calculate EquExpression value; generate tressel code and build new instruction objects
            Input Parameters: string equExpOperands (Operands of equExp instruction), string equLabel (possible Label of instruction)
            Output Parameters: none
            Error Conditions Tested: EquExp syntax check for multple operator, operator more than 6, label requred for equexp, use of label when equ required.
            Error Messages Generated: 
                    (See Error message table for descriptive messages)
                    [54,14,28]
            Original Author: Louis Pan/Ryan Mcdaniel
            Procedure Creation Date: 10/14/2009
            Modification Log:
            Who:Louis Pan   
            When: 10/16/2009    
            Why: Error message updated.
            Who: Louis Pan
            When: 10/20/2009
            Why:  When there is an error ParseEquExp no longer does output.
            Who: Louis Pan
            When: 11/4/2009
            Why:  checking literal in this.
            Who: Steve Rudy
            When: 11/12/2009
            Why: modified the Instruction constructor to include the isSourceGenerated value
            Coding standards met: SR
            Testing standards met: RM
            !*/

            equExpOperands = equExpOperands.Trim();


            /*#
            Variable Name: tempInstruction
            Module Where Defined: ParseEquExp
            Data Type: Instruction
            Local or Global: Local
            Purpose:  temp instance to bulid new instruction and call parse on it.
            #*/
            Instruction tempInstruction;
            /*#
            Variable Name: tempIndex
            Module Where Defined: ParseEquExp
            Data Type: int
            Local or Global: Local
            Purpose:  value for index of char in equExpOperands to check the operation character
            #*/
            int tempIndex = 0;
            hasLiteral = false;
            while (tempIndex < (equExpOperands.Length - 2))
            {
                if (equExpOperands[tempIndex].ToString().Contains("+") || equExpOperands[tempIndex].ToString().Contains("-") || equExpOperands[tempIndex].ToString().Contains("*") || equExpOperands[tempIndex].ToString().Contains("/"))
                {
                    if (equExpOperands[tempIndex + 1].ToString().Contains("+") || equExpOperands[tempIndex + 1].ToString().Contains("-") || equExpOperands[tempIndex + 1].ToString().Contains("*") || equExpOperands[tempIndex + 1].ToString().Contains("/"))
                    {
                        this.AddError(54);
                        shouldAddInstruction = 1;
                        return;
                    }
                }
                tempIndex++;
            }

            if (this.GetTotalOperators(equExpOperands) >= 6)
            {
                if (!equExpOperands.StartsWith("*"))
                {
                    this.AddError(14);
                    shouldAddInstruction = 1;
                    return;

                }
                else if (this.GetTotalOperators(equExpOperands) > 6)
                {
                    this.AddError(14);
                    shouldAddInstruction = 1;
                    return;
                }
            }
            else
            {


                System.Collections.ArrayList operands = new System.Collections.ArrayList();
                /*#
                Variable Name: tempOperator
                Module Where Defined: ParseEquExp
                Data Type: string
                Local or Global: Local
                Purpose:  To store temp operator for result caluclate
                #*/
                string tempOperator = " ";
                /*#
                Variable Name: substitutionString
                Module Where Defined: ParseEquExp
                Data Type: int
                Local or Global: Local
                Purpose:  value for the final result
                #*/
                int substitutionString;
                while (equExpOperands.Contains("+") || equExpOperands.Contains("-") || equExpOperands.Contains("*") || equExpOperands.Contains("/"))
                {
                    
                        /*#
                        Variable Name: indexOfFirstOperator
                        Module Where Defined: ParseEquExp
                        Data Type: int[]
                        Local or Global: Local
                        Purpose:  values for the first index of all 4 operators.
                        #*/
                        int[] indexOfFirstOperator = new int[4];
                        if (equExpOperands.Contains("+"))
                        {
                            indexOfFirstOperator[0] = equExpOperands.IndexOf("+");
                        }
                        else
                        {
                            indexOfFirstOperator[0] = 65;
                        }
                        if (equExpOperands.Contains("-"))
                        {
                            indexOfFirstOperator[1] = equExpOperands.IndexOf("-");
                        }
                        else
                        {
                            indexOfFirstOperator[1] = 65;
                        }
                        if (equExpOperands.Contains("*"))
                        {
                            indexOfFirstOperator[2] = equExpOperands.IndexOf("*");
                        }
                        else
                        {
                            indexOfFirstOperator[2] = 65;
                        }
                        if (equExpOperands.Contains("/"))
                        {
                            indexOfFirstOperator[3] = equExpOperands.IndexOf("/");
                        }
                        else
                        {
                            indexOfFirstOperator[3] = 65;
                        }
                        /*#
                        Variable Name: equExp
                        Module Where Defined: ParseEquExp
                        Data Type: string
                        Local or Global: Local
                        Purpose:  value for for the label name of equ-expression
                        #*/
                        string equExp = equExpOperands.Substring(0, indexOfFirstOperator.Min());
                        equExpOperands = equExpOperands.Remove(0, indexOfFirstOperator.Min());
                        System.Data.DataRow[] myRow = tresselReference.SymbolTable.Select("[Label Name]='" + equExp + "'");
                        if (myRow.Count() > 0)
                        {
                            if (((System.Data.DataRow)(myRow[0]))["Usage"].ToString().Equals("EQU"))
                            {
                                operands.Add(int.Parse((myRow[0]["Substitution String"]).ToString()));

                            }
                            else
                            {
                                this.AddError(28);
                                shouldAddInstruction = 1;
                                return;
                            }
                        }
                        else
                        {

                            tempIndex = 0;

                            while (tempIndex < equExp.Length)
                            {
                                if (!char.IsDigit(equExp[tempIndex]))
                                {
                                    this.AddError(14);
                                    shouldAddInstruction = 1;
                                    return;
                                }

                                tempIndex++;
                            }
                            operands.Add(int.Parse(equExp));//check error where equExp is an number or not.//changed
                        }
                        if (equExpOperands.Length > 0)      //changed
                        {
                            operands.Add(equExpOperands[0]);
                            equExpOperands = equExpOperands.Remove(0, 1);

                        }
                }

                System.Data.DataRow[] myRows = tresselReference.SymbolTable.Select("[Label Name]='" + equExpOperands + "'");
                if (myRows.Count() > 0)
                {
                    if (((System.Data.DataRow)(myRows[0]))["Usage"].ToString().Equals("EQU"))
                    {
                        operands.Add(int.Parse((myRows[0]["Substitution String"]).ToString()));

                    }
                    else
                    {
                        this.AddError(28);
                        shouldAddInstruction = 1;
                        return;
                    }
                }
                else
                {

                    tempIndex = 0;

                    while (tempIndex < equExpOperands.Length)
                    {
                        if (!char.IsDigit(equExpOperands[tempIndex]))
                        {
                            this.AddError(14);
                            shouldAddInstruction = 1;
                            return;
                        }

                        tempIndex++;
                    }
                    operands.Add(int.Parse(equExpOperands));
                }

                equExpOperands = equExpOperands.Remove(0);
                substitutionString = int.Parse(operands[0].ToString());
                operands.RemoveAt(0);
                if (equExpOperands.EndsWith("+") || equExpOperands.EndsWith("-") || equExpOperands.EndsWith("*") || equExpOperands.EndsWith("/"))
                {
                    this.AddError(14);
                    shouldAddInstruction = 1;
                    return;
                }
                while (operands.Count > 0)
                {
                    if (operands.Count > 0)
                    {
                        tempOperator = operands[0].ToString();
                        operands.RemoveAt(0);
                    }

                    switch (tempOperator)
                    {
                        case "+":
                            {
                                substitutionString += int.Parse(operands[0].ToString());
                                operands.Remove(0);
                                break;
                            }

                        case "-":
                            {
                                substitutionString -= int.Parse(operands[0].ToString());
                                operands.Remove(0);
                                break;
                            }

                        case "*":
                            {
                                substitutionString *= int.Parse(operands[0].ToString());
                                operands.Remove(0);
                                break;
                            }

                        case "/":
                            {
                                if (int.Parse(operands[0].ToString()) == 0)
                                {
                                    AddError(48);
                                    shouldAddInstruction = 1;
                                    return;
                                }
                                substitutionString /= int.Parse(operands[0].ToString());
                                operands.Remove(0);
                                break;
                            }

                    }
                }
                iOperands.Text = substitutionString.ToString();

            }
            this.iOpcode.Text = "EQU";
            tresselReference.InsertSymbol(this.iLabel.Text, "", "EQU", iOperands.Text, "");

        }

        private void ParseComp(string compOperands, string compLabel)
        {
            /*!
             Procedure Name: ParseComp
             Description: The method to generate tressel code and build new instruction objects of the equivalent code of Comp
             Input Parameters: string compOerands (Operands of Comp instruction), string compLabel (possible Label of instruction)
             Output Parameters: none
             Error Conditions Tested: Label = are at the beginning of operand,Invalid order of calculation and Number of opoerators in the operand
             Error Messages Generated: 
                      (See Error message table for descriptive messages)
                       [6]
             Original Author: Louis Pan/Ryan Mcdaniel
             Procedure Creation Date: 10/12/2009
             Modification Log:
             Who:Louis Pan/Ryan McDaniel
             When: 10/14/2009
             Why:  Method was not complete on 10/12/2009.  Complete the parsing of operands with leading positive or negative operators.
             Who:Louis Pan   
             When: 10/16/2009
             Why: Change the checks for " " and "\t" for the operands because the parse takes care of it.
             Who: Louis Pan
             When: 10/20/2009
             Why: In order to better handle negatives, the operations are reversed then stored to a negative variable.  Indexes are double checked for errors.
             Who: Louis Pan
             When: 11/11/2009
             Why: operand for negative didn't switch sign. fixed.
             Who: Steve Rudy
             When: 11/12/2009
             Why: modified the Instruction constructor to include the isSourceGenerated value
             Who : LP , RM
             When: 11/12/2009
             Why: redesign comp computation.make a real time stack in mechine.
             Who: LP
             When: 11/14/2009
             why: insert nop to store the value from calculation result.
             Coding standards met: SR
             Testing standards met: RM
             !*/



            /*#
            Variable Name: tempInstruction
            Module Where Defined: ParseComp
            Data Type: Instruction
            Local or Global: Local
            Purpose:  Instruction that temporary keep the new instruction and call parse on it. 
            #*/
            Instruction tempInstruction;
            System.Collections.Stack storeOperations = new System.Collections.Stack();
            compOperands = compOperands.Trim();
            if (compOperands.IndexOf("=") < 1 || compOperands[compOperands.Length - 1].Equals('*') || compOperands[compOperands.Length - 1].Equals('/') || compOperands[compOperands.Length - 1].Equals('+') || compOperands[compOperands.Length - 1].Equals('-'))
            {
                this.AddError(6);
                this.SetToNop();
                return;
            }
            else
            {
                /*#
                Variable Name: equalsIndex
                Module Where Defined: ParseComp
                Data Type: int
                Local or Global: Local
                Purpose:  index of = character
                #*/
                int equalsIndex = compOperands.IndexOf("=");
                /*#
                Variable Name: initializedLabel
                Module Where Defined: ParseComp
                Data Type: Instruction
                Local or Global: Local
                Purpose: value of label where comp resule is stored. 
                #*/
                Label initializedLabel = new Label(compOperands.Substring(0, equalsIndex), this);
                if (initializedLabel.ErrorFlag)
                {
                    this.AddError(6);
                    this.SetToNop();
                    return;
                }

                compOperands = compOperands.Remove(0, equalsIndex + 1);

                if (compOperands.StartsWith("*") || compOperands.StartsWith("/"))
                {
                    this.AddError(6);
                    this.SetToNop();
                    return;
                }
                else
                {
                    if (this.hasDoubleOperator(compOperands))
                    {
                        this.AddError(6);
                        this.SetToNop();
                        return;
                    }
                    else
                    {
                        if (this.GetTotalOperators(compOperands) > 5)
                        {
                            this.AddError(6);
                            this.SetToNop();
                            return;
                        }
                        else
                        {
                            /*#
                            Variable Name: multAndDinide
                            Module Where Defined: ParseComp
                            Data Type: char[]
                            Local or Global: Local
                            Purpose:  set for operators * and /
                            #*/
                            char[] multAndDivide = { '*', '/' };
                            /*#
                            Variable Name: addAndSubtract
                            Module Where Defined: ParseComp
                            Data Type: char[]
                            Local or Global: Local
                            Purpose:  set for operators + and - 
                            #*/
                            char[] addAndSubtract = { '+', '-' };
                            /*#
                            Variable Name: someOperator
                            Module Where Defined: ParseComp
                            Data Type: char[]
                            Local or Global: Local
                            Purpose:  set for operators +,-, * and /
                            #*/
                            char[] someOperator = { '+', '-', '*', '/' };
                            /*#
                            Variable Name: finalString
                            Module Where Defined: ParseComp
                            Data Type: string
                            Local or Global: Local
                            Purpose:  value to keep the operands in reverse polish notation
                            #*/
                            string finalString = "";
                            /*#
                            Variable Name: finalString
                            Module Where Defined: ParseComp
                            Data Type: bool
                            Local or Global: Local
                            Purpose:  boolean value to keep check where first operands is negitive
                            #*/
                            bool isNegativecompOperands;
                            isNegativecompOperands = compOperands.StartsWith("-");
                            if (compOperands.StartsWith("+") || compOperands.StartsWith("-"))
                            {
                                compOperands = compOperands.Remove(0, 1);
                            }
                            if (isNegativecompOperands)
                            {

                                compOperands = compOperands.Replace('+', '&');
                                compOperands = compOperands.Replace('-', '+');
                                compOperands = compOperands.Replace('&', '-');


                            }
                            
                            while (compOperands.Contains("*") || compOperands.Contains("/"))
                            {
                                /*#
                                Variable Name: list
                                Module Where Defined: ParseComp
                                Data Type: string[]
                                Local or Global: Local
                                Purpose:  string arraylist to store value from split
                                #*/
                                string[] list = compOperands.Split(multAndDivide, 2, StringSplitOptions.None);
                                /*#
                                Variable Name: multOrDivide
                                Module Where Defined: ParseComp
                                Data Type: char
                                Local or Global: Local
                                Purpose:  keep multiple or divide operator
                                #*/
                                char multOrDivide = compOperands[list[0].Length];
                                /*#
                                Variable Name: firstHalf
                                Module Where Defined: ParseComp
                                Data Type: string
                                Local or Global: Local
                                Purpose:  string of first labels before operator multOrDivide 
                                #*/
                                string firstHalf = list[0].ToString();
                                compOperands = list[1].ToString();

                                list = compOperands.Split(someOperator, 2, StringSplitOptions.None);
                                /*#
                                Variable Name: secondOperator
                                Module Where Defined: ParseComp
                                Data Type: char
                                Local or Global: Local
                                Purpose:  keep the value of operator been splited from
                                #*/

                                finalString += firstHalf + ',' + list[0].ToString() + ',' + multOrDivide + ',';
                                if (compOperands.Length > list[0].Length)
                                {
                                    char secondOperator = compOperands[list[0].Length];
                                    compOperands = secondOperator + list[1];
                                }
                                else
                                {
                                    compOperands = "";
                                }

                            }
                            compOperands = finalString + compOperands;
                            finalString = "";
                            while (compOperands.Contains("+") || compOperands.Contains("-"))
                            {
                                /*#
                                Variable Name: list(2)
                                Module Where Defined: ParseComp
                                Data Type: string[]
                                Local or Global: Local
                                Purpose:  string arraylist to store value from split
                                #*/
                                string[] list = compOperands.Split(addAndSubtract, 2, StringSplitOptions.None);
                                /*#
                                Variable Name: firstOperator
                                Module Where Defined: ParseComp
                                Data Type: char
                                Local or Global: Local
                                Purpose:  keep the first operator value
                                #*/
                                char firstOperator = compOperands[list[0].Length];
                                /*#
                                Variable Name: firstHalf (2)
                                Module Where Defined: ParseComp
                                Data Type: string
                                Local or Global: Local
                                Purpose:  string of first labels before operator someOperator 
                                #*/
                                string firstHalf = list[0].ToString();
                                compOperands = list[1].ToString();

                                list = compOperands.Split(addAndSubtract, 2, StringSplitOptions.None);


                                finalString += firstHalf + ',' + list[0].ToString() + ',' + firstOperator + ',';
                                if (compOperands.Length > list[0].Length)
                                {
                                    /*#
                                    Variable Name: secondOperator (2)
                                    Module Where Defined: ParseComp
                                    Data Type: char
                                    Local or Global: Local
                                    Purpose:  keep the value of operator been splited from
                                    #*/
                                    char secondOperator = compOperands[list[0].Length];
                                    compOperands = secondOperator + list[1];
                                }
                                else
                                {
                                    compOperands = "";
                                }
                            }
                            compOperands = finalString + compOperands;

                            /*#
                            Variable Name: firstOperation
                            Module Where Defined: ParseComp
                            Data Type: bool
                            Local or Global: Local
                            Purpose:  check value of first operation
                            #*/
                            bool firstOperation = true;
                            if( !(compOperands.Contains("+") || compOperands.Contains("-") || compOperands.Contains("*") || compOperands.Contains("/")))
                            {
                                string function = "";
                                if (isNegativecompOperands)
                                {
                                    function = " LDN-AC ";
                                }
                                else
                                {
                                    function = " LD-AC ";
                                }

                                if (!char.IsDigit(compOperands[0]))
                                {
                                    
                                    tempInstruction = new Instruction(compLabel + function + compOperands, this.tresselReference, false);
                                }
                                else
                                {
                                    tempInstruction = new Instruction(compLabel + function + compOperands, this.tresselReference, false);
                                }
                                tempInstruction.Parse();
                                return;
                            }
                            while (compOperands.Length > 0)
                            {
                                /*#
                                Variable Name: commaIndex
                                Module Where Defined: ParseComp
                                Data Type: int
                                Local or Global: Local
                                Purpose:  index of first comma
                                #*/
                                int commaIndex = compOperands.IndexOf(",");
                                /*#
                                Variable Name: firstLabel
                                Module Where Defined: ParseComp
                                Data Type: string
                                Local or Global: Local
                                Purpose:  value of first label in the Operands
                                #*/
                                string firstLabel = compOperands.Substring(0, commaIndex);
                                compOperands = compOperands.Remove(0, commaIndex);
                                while (compOperands.StartsWith(","))
                                {
                                    compOperands = compOperands.Remove(0, 1);
                                }
                                if (!(firstLabel.Contains("+") || firstLabel.Contains("-") || firstLabel.Contains("*") || firstLabel.Contains("/")))
                                {
                                    storeOperations.Push(firstLabel);
                                }
                                else
                                {
                                    #region MyRegion
                                    //if (firstOperation)
                                    //{
                                        /*#
                                        Variable Name: pop2
                                        Module Where Defined: ParseComp
                                        Data Type: string
                                        Local or Global: Local
                                        Purpose:  first Label to be pop from the stack
                                        #*/
                                        string pop2 = storeOperations.Pop().ToString();
                                        /*#
                                        Variable Name: pop1
                                        Module Where Defined: ParseComp
                                        Data Type: string
                                        Local or Global: Local
                                        Purpose:  second Label to be pop from the stack
                                        #*/
                                        string pop1 = storeOperations.Pop().ToString();

                                        
                                        /*#
                                        Variable Name: function
                                        Module Where Defined: ParseComp
                                        Data Type: string
                                        Local or Global: Local
                                        Purpose:  opcode name from operator to tressel code.
                                        #*/
                                        string function = "";
                                        if (!firstOperation)
                                        {
                                            compLabel = "";
                                        }
                                        firstOperation = false;
                                        if (!char.IsDigit(pop1[0]))
                                        {

                                            if (pop1.StartsWith ("&"))
                                            {
                                                pop1 = pop1.Remove(0, 1);
                                            }
                                                tempInstruction = new Instruction(compLabel + " LD-AC " + pop1, this.tresselReference, false);
                                        }
                                        else
                                        {
                                            tempInstruction = new Instruction(compLabel + " LD-AC =" + pop1, this.tresselReference,false);
                                        }
                                        tempInstruction.Parse();
                                        switch (firstLabel)
                                        {
                                            case "+":
                                                {
                                                    function = " ADD-AC ";
                                                    break;
                                                }

                                            case "-":
                                                {
                                                    function = " SUB-AC ";
                                                    break;
                                                }
                                            case "*":
                                                {
                                                    function = " MUL-AC ";
                                                    break;
                                                }
                                            case "/":
                                                {

                                                    function = " DIV-AC ";
                                                    break;
                                                }

                                        }
                                        if (!char.IsDigit(pop2[0]))
                                        {
                                            if (pop2.StartsWith("&"))
                                            {
                                                pop2 = pop2.Remove(0, 1);
                                            }
                                            tempInstruction = new Instruction(function + pop2, this.tresselReference,false);
                                        }
                                        else
                                        {
                                            tempInstruction = new Instruction(function + "=" + pop2, this.tresselReference,false);
                                        }
                                        
                                        tempInstruction.Parse();
                                    //}
                                        tempInstruction = new Instruction(" ST-AC " + (tempInstruction.ILocationCount+3).ToString(), this.tresselReference, false);
                                        tempInstruction.Parse();
                                        tempInstruction = new Instruction(" JMP " + (tempInstruction.ILocationCount+ 3).ToString(), this.tresselReference, false);
                                        tempInstruction.Parse();
                                        tempInstruction = new Instruction(" NOP ", this.tresselReference, false);
                                        tempInstruction.Parse();
                                        storeOperations.Push(("&"+(tempInstruction.ILocationCount).ToString()));
                               
                                    #endregion
                                }
                            }



                            if (isNegativecompOperands)
                            {
                                tempInstruction = new Instruction(" MUL-AC =-1", this.tresselReference,false);
                                tempInstruction.Parse();
                            }
                            tempInstruction = new Instruction(" ST-AC " + initializedLabel.Text, this.tresselReference, false);
                            tempInstruction.Parse();
                        }
                    }
                }
            }
        }

        private bool hasDoubleOperator(string lineToCheck)
        {
            /*!
            Procedure Name: HasDoubleOperator
            Description: A check to see if moore than one mathematical operator is used consecutively.
            Input Parameters: string lineToCheck(The string of operators and symbols)
            Output Parameters: none
            Error Conditions Tested: 
            Error Messages Generated: 
            Original Author: Steve Rudy/Ryan McDaniel
            Procedure Creation Date: 10/13/2009
            Modification Log:
            Coding standards met: SR
            Testing standards met: RM
            !*/

            /*#
            Variable Name: operatorIndex
            Module Where Defined: hasDoubleOperator
            Data Type: int
            Local or Global: Local
            Purpose:  value for the index of a operator.
            #*/
            int operatorIndex = 0;
            while (operatorIndex < lineToCheck.Length - 1)
            {
                if (lineToCheck[operatorIndex].Equals('*') || lineToCheck[operatorIndex].Equals('/') || lineToCheck[operatorIndex].Equals('-') || lineToCheck[operatorIndex].Equals('+'))
                {
                    if (lineToCheck[operatorIndex + 1].Equals('*') || lineToCheck[operatorIndex + 1].Equals('/') || lineToCheck[operatorIndex + 1].Equals('-') || lineToCheck[operatorIndex + 1].Equals('+'))
                    {
                        return true;
                    }
                }
                operatorIndex++;
            }
            return false;
        }
        private int GetTotalOperators(string lineToCheck)
        {
            /*!
            Procedure Name: GetTotalOperators
            Description: A method to find the total number of mathematical operators in a string
            Input Parameters: string lineToCheck(The string of operators and symbols)
            Output Parameters: none
            Error Conditions Tested: 
            Error Messages Generated: 
            Original Author: Steve Rudy/Ryan McDaniel
            Procedure Creation Date: 10/13/2009
            Modification Log:
            Coding standards met: SR
            Testing standards met: RM
            !*/

            /*#
            Variable Name: totalOperators
            Module Where Defined: GetTotalOperators
            Data Type: int
            Local or Global: Local
            Purpose:  value for the total number of operators.
            #*/
            int totalOperators = 0;
            for (int i = 0; i < lineToCheck.Length; i++)
            {
                if (lineToCheck[i].Equals('*') || lineToCheck[i].Equals('/') || lineToCheck[i].Equals('+') || lineToCheck[i].Equals('-'))
                {
                    totalOperators++;
                }
            }
            return totalOperators;
        }
        private string TrimNextWord()
        {
            /*!
            Procedure Name: TrimNextWord
            Description: returns the next word from the string and as well as removing it from the
            string passed in
            Input Parameters: none
            Output Parameters: none
            Error Conditions Tested: 
            Error Messages Generated: 
            Original Author: Steve Rudy
            Procedure Creation Date: 10/11/2009
            Modification Log:
            Coding standards met: SR
            Testing standards met: RM
            !*/

            /*#
            Variable Name: whitespace
            Module Where Defined: TrimNextWord
            Data Type: char[]
            Local or Global: Local
            Purpose:  set of space and tab that help parse a string line
            #*/
            char[] whitespace = { ' ', '\t' };
            /*#
            Variable Name: firstWord
            Module Where Defined: TrimNextWord
            Data Type: string
            Local or Global: Local
            Purpose:  value for the frist word in instructionString
            #*/
            string firstWord = "";
            instructionString = instructionString.TrimStart(whitespace);
            if (instructionString.Length > 0)
            {
                /*#
                Variable Name: spaceIndex
                Module Where Defined: TrimNextWord
                Data Type: int
                Local or Global: Local
                Purpose:  value for the frist space index
                #*/
                int spaceIndex = instructionString.IndexOf(' ');
                /*#
                Variable Name: tabIndex
                Module Where Defined: TrimNextWord
                Data Type: int
                Local or Global: Local
                Purpose:  value for the frist tab index
                #*/
                int tabIndex = instructionString.IndexOf('\t');
                /*#
                Variable Name: whiteSpaceIndex
                Module Where Defined: TrimNextWord
                Data Type: int
                Local or Global: Local
                Purpose:  value for the frist whiteSpace index
                #*/
                int whiteSpaceIndex = -1;
                if (spaceIndex > tabIndex)
                {
                    if (tabIndex == -1)
                    {
                        whiteSpaceIndex = spaceIndex;
                    }
                    else
                    {
                        whiteSpaceIndex = tabIndex;
                    }
                }
                else if (tabIndex >= spaceIndex)
                {
                    if (spaceIndex == -1)
                    {
                        whiteSpaceIndex = tabIndex;
                    }
                    else
                    {
                        whiteSpaceIndex = spaceIndex;
                    }
                }
                if (whiteSpaceIndex != -1)
                {
                    firstWord = instructionString.Substring(0, whiteSpaceIndex);
                    instructionString = instructionString.Substring(whiteSpaceIndex);
                }
                else
                {
                    firstWord = instructionString;
                    instructionString = "";
                }
            }
            return firstWord;
        }
        #endregion
    }
}